(function() {
	/**
	 * 全局方法入口
	 */
	CS = {};

	/**
	 * 数据处理
	 */
	Ext.apply(CS, {
		/**
		 * 去掉字符串左右空格
		 */
		trim: function(str) {
			return str.replace(/^(\s|\u00A0)+/, '').replace(/(\s|\u00A0)+$/, '');
		},
		/**
		 * 判断字符串是否包含某字符串
		 */
		contains: function(str, searchStr) {
			if (str.indexOf(searchStr) != -1) {
				return true;
			} else {
				return false;
			}
		},
		/**
		 * 是否不为空
		 */
		isNotEmpty: function(value) {
			return !CS.isEmpty(value);
		},
		/**
		 * 是否为空
		 */
		isEmpty: function(value) {
			if (Ext.isString(value)) {
				value = CS.trim(value);
			}

			if (Ext.isEmpty(value)) {
				return true;
			}

			return false;
		},
		/**
		 * 是否不为null和undefined
		 */
		isNotNull: function(value) {
			return !CS.isNull(value);
		},
		/**
		 * 是否为null和undefined
		 */
		isNull: function(value) {
			if (!Ext.isDefined(value) || value == null) {
				return true;
			}

			return false;
		},
		/**
		 * 对象转换成JSON格式字符串
		 */
		toJson: function(obj) {
			return Ext.encode(obj);
		},
		/**
		 * JSON格式字符串转换成对象
		 */
		fromJson: function(json) {
			return Ext.decode(json);
		},
		/**
		 * 复制属性
		 */
		apply: function(object, config, defaults) {
			if (defaults) {
				Ext.applyIf(object, defaults);
			}

			return Ext.apply(object, config);
		},
		/**
		 * 复制已存在的属性
		 */
		applyExist: function(object, config) {
			var property;

			if (object) {
				for (property in config) {
					if (CS.isNotNull(object[property])) {
						object[property] = config[property];
					}
				}
			}

			return object;
		},
		/**
		 * 大小写转换，默认为大写转换
		 */
		toCase: function(value, isLow) {
			if (CS.isNull(value)) {
				return '';
			}

			return (value + '')[isLow ? 'toLowerCase' : 'toUpperCase']();
		},
		/**
		 * 获取布尔值
		 */
		getBoolean: function(value, defaultValue) {
			if (CS.isNull(value)) {
				if (CS.isNotNull(defaultValue)) {
					value = defaultValue;
				} else {
					return false;
				}
			}

			if (CS.toCase(value) === 'TRUE' || value === 'Y' || value === 1 || value === true) {
				return true;
			} else if (CS.toCase(value) === 'FALSE' || value === 'N' || value === 0 || value === false) {
				return false;
			} else {
				return null;
			}
		},
		/**
		 * 是否等于其中某个值
		 */
		equalOne: function(value, arr) {
			for (var i = 0; i < arr.length; i++) {
				if (value === arr[i]) {
					return true;
				}
			}

			return false;
		}
	});

	/**
	 * 配置处理
	 */
	Ext.apply(CS, {
		/**
		 * 转换配置值
		 */
		transConfigValue: function(config) {
			var param;

			for (param in config) {
				if (Ext.isNumeric(config[param])) {
					config[param] *= 1;
				} else if (CS.equalOne(config[param], ['true', 'false'])) {
					config[param] = CS.getBoolean(config[param]);
				}
			}
			return config;
		},
		/**
		 * 转换配置属性名
		 */
		transConfigParam: function(config, transform) {
			var param;

			for (param in transform) {
				var old = transform[param];

				if (CS.isNotNull(config[old])) {
					config[param] = config[old];
					delete config[old];
				}
			}
		},
		/**
		 * 把“key:value,key:value,...”这种类型的字符串转换成对象
		 */
		transKeyValue: function(str) {
			var obj = {}, paramArr = str.split(',');

			Ext.each(paramArr, function(param) {
				var info = param.split(':');
				obj[info[0]] = info[1];
			});

			return obj;
		},
		/**
		 * 设置默认属性
		 */
		setDefaultConfig: function(config, defaultConfig) {
			Ext.applyIf(config, defaultConfig);
		},
		/**
		 * 根据class名称组装数据
		 */
		getPackageData: function(data, clsName, notNeedCls) {
			if (CS.isEmpty(clsName) || notNeedCls == true) {
				return data;
			} else {
				var realData = {};
				realData[clsName] = data;
				return realData;
			}
		},
		/**
		 * 注册控件
		 */
		register: function(config) {
			var param;

			for (param in config) {
				Ext.ClassManager.setAlias(param, config[param]);
			}
		}
	});

	window.rootUrl = window.rootUrl || '';
	window.moduleUrl = window.moduleUrl || '';

	/**
	 * 远程服务
	 */
	Ext.apply(CS, {
		/**
		 * 获取完整路径
		 */
		getUrl: function(url, type) {
			var preUrl;

			url = url || '';

			type = type || 'r';

			switch (type) {
			case 'r':
				preUrl = window.rootUrl;
				break;
			case 'm':
				preUrl = window.moduleUrl;
				break;
			}

			return (preUrl + url).replace(/\/{2,}/g, '/').replace(/\/$/, '');
		},
		/**
		 * 从根路径开始，获取完整路径
		 */
		getRootUrl: function(url) {
			return CS.getUrl(url, 'r');
		},
		/**
		 * 从当前模块路径开始，获取完整路径
		 */
		getModuleUrl: function(url) {
			return CS.getUrl(url, 'm');
		},
		/**
		 * 请求服务器
		 */
		request: function(options) {
			if (options.toModule == true) {
				options.url = CS.getRootUrl(options.url);
			} else {
				options.url = CS.getModuleUrl(options.url);
			}

			var doRequest = function() {
				if (options.ajax == false) {
					if (options.lock) {
						CS.lock('正在跳转，请稍等...', false);
					}
					window.location.href = options.url;
				} else {
					if (options.lock) {
						CS.lock(options.lockMsg);
					}

					function transFn(fn) {
						var newFn;

						if (fn) {
							newFn = function(response, opt) {
								var obj = null;

								if (!CS.isNull(response.responseText)) {
									obj = Ext.decode(response.responseText);
								}

								fn.apply(this, [obj, opt]);

								if (options.lock) {
									CS.unlock();
								}
							};
						}

						return newFn;
					}

					Ext.Ajax.request({
						url: options.url,
						jsonData: options.data,
						success: transFn(options.succ),
						failure: transFn(options.error)
					});
				}
			}

			if (CS.isNotEmpty(options.confirm)) {
				CS.confirm(options.confirm, function() {
					doRequest();
				});
			} else {
				doRequest();
			}
		},
		/**
		 * Ajax请求
		 */
		ajax: function(options) {
			options.ajax = true;
			CS.request(options);
		},
		/**
		 * 提交资源
		 */
		submit: function(options) {
			options.lock = true;
			CS.ajax(options);
		},
		/**
		 * 跳转页面
		 */
		run: function(url, lock) {
			CS.request({
				url: url,
				ajax: false,
				lock: CS.getBoolean(lock, true)
			});
		},
		/**
		 * 把对象转换为“key1=value1&key2=value2...”这样的请求参数格式
		 */
		param: function(obj) {
			var arr = [];

			for ( var prefix in obj) {
				CS.buildParams(prefix, obj[prefix], arr);
			}

			return arr.join("&").replace(/%20/g, '+');
		},
		/**
		 * 把obj以“key=value”格式的字符串放到arr数组中
		 */
		buildParams: function(prefix, obj, arr) {
			if (CS.isNull(obj)) {
				obj = '';
			}

			if (Ext.isArray(obj) && CS.isNotEmpty(obj)) {
				for (var i = 0; i < obj.length; i++) {
					var v = obj[i];
					buildParams(prefix + '[' + (Ext.isObject(v) || Ext.isArray(v) ? i : '') + ']', v, arr);
				}
			} else if (Ext.isObject(v)) {
				for (name in obj) {
					buildParams(prefix + '[' + name + ']', obj[name], arr);
				}
			} else {
				arr[arr.length] = encodeURIComponent(prefix) + '=' + encodeURIComponent(obj);
			}
		}
	});

	/**
	 * 提示框
	 */
	Ext.apply(CS, {
		/**
		 * 警告提示框
		 */
		alert: function() {
			var arg = [{
				title: '提示',
				icon: Ext.Msg.WARNING
			}];

			CS.showMsg.apply(this, arg.concat(Array.prototype.slice.call(arguments, 0)));
		},
		/**
		 * 错误提示框
		 */
		error: function() {
			var arg = [{
				title: '错误',
				icon: Ext.Msg.ERROR
			}];

			CS.showMsg.apply(this, arg.concat(Array.prototype.slice.call(arguments, 0)));
		},
		/**
		 * 信息提示框
		 */
		info: function() {
			var arg = [{
				title: '信息',
				icon: Ext.Msg.INFO
			}];

			CS.showMsg.apply(this, arg.concat(Array.prototype.slice.call(arguments, 0)));
		},
		/**
		 * 信息确认框
		 */
		confirm: function(msg, okFn, cancelFn) {
			var cfg = {
				title: '信息确认',
				icon: Ext.Msg.QUESTION,
				msg: msg,
				buttons: [{
					text: '确定',
					fn: okFn
				}, {
					text: '取消',
					fn: cancelFn
				}]
			};

			CS.complexMsg.apply(this, [cfg]);
		},
		/**
		 * 复杂提示框
		 */
		complexMsg: function(cfg) {
			var buttons = cfg.buttons, buttonNum = {
				1: Ext.Msg.YES,
				2: Ext.Msg.YESNO,
				3: Ext.Msg.YESNOCANCEL
			}, buttonIds = ['yes', 'no', 'cancel'], buttonFn = {};

			cfg.buttons = buttonNum[buttons.length];

			cfg.buttonText = {};
			for (var i = 0; i < 3 && i < buttons.length; i++) {
				var button = buttons[i];
				cfg.buttonText[buttonIds[i]] = button.text;
				buttonFn[buttonIds[i]] = button.fn || Ext.emptyFn;
			}

			cfg.fn = function(buttonId) {
				for (var i = 0; i < buttonIds.length; i++) {
					if (buttonId == buttonIds[i]) {
						buttonFn[buttonIds[i]]();
					}
				}
			};

			var arg = [cfg];

			CS.showMsg.apply(this, [cfg]);
		},
		/**
		 * 基础提示框
		 */
		showMsg: function() {
			var option = arguments[0];

			option.closable = false;

			if (option.wait != true && option.buttons == undefined) {
				option.buttons = Ext.Msg.OK;
			}

			switch (arguments.length) {
			case 2:
				option.msg = arguments[1];
				break;
			case 3:
				if (Ext.isFunction(arguments[2])) {
					option.msg = arguments[1], option.fn = arguments[2];
				} else {
					option.title = arguments[1], option.msg = arguments[2];
				}
				break;
			case 4:
				option.title = arguments[1], option.msg = arguments[2], option.callback = arguments[3];
				break;
			}

			Ext.Msg.show(option);
		},
		/**
		 * 锁屏
		 */
		lock: function(message, unlockable) {
			CS.showMsg({
				isLock: true,
				unlockable: CS.isNull(unlockable) ? true : unlockable,
				msg: message || '正在提交，请稍等...',
				wait: true,
				waitConfig: {
					interval: 200
				}
			});
		},
		/**
		 * 去掉锁屏
		 */
		unlock: function() {
			var cfg = Ext.Msg.cfg;

			if (cfg.isLock && cfg.unlockable) {
				Ext.MessageBox.hide();
			}
		}
	});

	/**
	 * DOM操作
	 */
	Ext.apply(CS, {
		/**
		 * 创建控件
		 */
		create: function(config) {
			return Ext.widget(config);
		},
		/**
		 * 绑定事件
		 */
		bind: function(cmp, eventName, fn, scope) {
			scope = scope || cmp;

			cmp.addListener(eventName, fn, scope);
		}
	});

	/**
	 * 页面静态方法，需要设置mainPanel属性
	 */
	Ext.apply(CS, {
		/**
		 * 主面板
		 */
		mainPanel: undefined,
		/**
		 * 获取页面主面板
		 */
		getMain: function() {
			return CS.mainPanel;
		},
		/**
		 * 获取页面标题
		 */
		getTitle: function() {
			return CS.getMain().pageTitle;
		},
		/**
		 * 获取页面数据
		 */
		getData: function(notNeedCls) {
			return CS.getMain().getData(notNeedCls);
		},
		/**
		 * 设置页面数据
		 */
		setData: function(data, notNeedCls) {
			CS.getMain().setData(data, notNeedCls);
		},
		/**
		 * 清空页面数据
		 */
		clear: function() {
			return CS.getMain().clear();
		},
		/**
		 * 根据ID获取控件
		 */
		get: function(id) {
			return CS.find('#' + id, true);
		},
		/**
		 * 根据选择符查询控件
		 */
		find: function(selector, onlyOne) {
			var arr = Ext.ComponentQuery.query(selector);

			if (CS.isNotEmpty(arr)) {
				if (onlyOne == true) {
					return arr[0];
				} else {
					return arr;
				}
			} else {
				return null;
			}
		},
		/**
		 * 显示控件
		 */
		show: function(comp) {
			if (Ext.isString(comp)) {
				comp = CS.get(comp);
			}

			if (comp) {
				var tabPanel = comp.up('tabpanel', 1);

				if (tabPanel && comp.tab) {
					tabPanel.showTab(comp);
				} else {
					comp.show();
				}
			}
		},
		/**
		 * 隐藏控件
		 */
		hide: function(comp) {
			if (Ext.isString(comp)) {
				comp = CS.get(comp);
			}

			if (comp) {
				var tabPanel = comp.up('tabpanel', 1);

				if (tabPanel && comp.tab) {
					tabPanel.hideTab(comp);
				} else {
					comp.hide();
				}
			}
		},
		/**
		 * 设置只读属性
		 */
		setReadOnly: function(readOnly) {
			return CS.getMain().setReadOnly(readOnly);
		}
	});
})();

Ext.Loader.setPath({
	'CS': CS.getRootUrl('resource/cs/ext/src')
});

/**
 * 注册控件
 */
CS.register({
	/**
	 * 字段
	 */
	'CS.field.BaseField': 'widget.field.base',
	'CS.field.Combo': 'widget.field.combo',
	'CS.field.Date': 'widget.field.date',
	'CS.field.Number': 'widget.field.number',
	'CS.field.Password': 'widget.field.password',
	'CS.field.Text': 'widget.field.text',
	/**
	 * 面板
	 */
	'CS.panel.BasePanel': 'widget.panel.base',
	'CS.panel.EditGrid': 'widget.panel.egrid',
	'CS.panel.Fit': 'widget.panel.fit',
	'CS.panel.Form': 'widget.panel.form',
	'CS.panel.Grid': 'widget.panel.grid',
	'CS.panel.HBox': 'widget.panel.hbox',
	'CS.panel.List': 'widget.panel.list',
	'CS.panel.Multi': 'widget.panel.multi',
	'CS.panel.Pie': 'widget.panel.pie',
	'CS.panel.Tab': 'widget.panel.tab',
	'CS.panel.Tree': 'widget.panel.tree',
	'CS.panel.VBox': 'widget.panel.vbox',
	'CS.panel.View': 'widget.panel.view',
	'CS.panel.Win': 'widget.panel.win',
	/**
	 * 页面
	 */
	'CS.page.Main': 'widget.page.main',
	/**
	 * 代理
	 */
	'CS.data.proxy.Custom': 'proxy.custom',
	/**
	 * 数据渲染
	 */
	'CS.data.reader.Tree': 'reader.tree',
	/**
	 * 插件
	 */
	'CS.plugin.FieldDataDeal': 'plugin.fielddatadeal',
	'CS.plugin.FieldDomDeal': 'plugin.fielddomdeal',
	'CS.plugin.GridRender': 'plugin.gridrender',
	'CS.plugin.PanelDataDeal': 'plugin.paneldatadeal',
	'CS.plugin.PanelDomDeal': 'plugin.paneldomdeal',
});
Ext.define('CS.config.BaseConfig', {

	config: undefined,

	initConfig: Ext.emptyFn,

	constructor: function(config) {
		var me = this;

		if (Ext.isString(config)) {
			config = Ext.decode(config);
		}

		me.initDefaultConfig(config);
		me.initConfig(config);
		me.initPlugins(config);

		me.config = config;
	},

	initDefaultConfig: function(config) {
		var me = this;

		if (CS.isNotNull(config.proMap)) {
			CS.transConfigValue(config.proMap);

			CS.apply(config, config.proMap);
			delete config.proMap;
		}

		if (CS.isNotNull(me.transform)) {
			CS.transConfigParam(config, me.transform);
		}

		if (CS.isNotNull(me.defaultConfig)) {
			CS.setDefaultConfig(config, me.defaultConfig);
		}

		if (CS.isNotEmpty(config.url)) {
			config.url = CS.getRootUrl(config.url);
		}

		config.extendParam = {};
		if (CS.isNotEmpty(config.params)) {
			config.extendParam = CS.transKeyValue(config.params);

			CS.transConfigValue(config.extendParam);

			delete config.params;
		}
	},

	initPlugins: function(config) {
		if (CS.isNotEmpty(config.plugins)) {
			config.plugins = config.plugins.split(',');
		} else {
			config.plugins = [];
		}

		if (CS.isNotNull(this.defaultPlugins)) {
			config.plugins = config.plugins.concat(this.defaultPlugins);
		}
	},

	getConfig: function() {
		return this.config;
	}

});
Ext.define('CS.controller.PageController', {

	mainPanel: undefined,

	eventItems: undefined,

	constructor: function(config) {
		CS.apply(this, config);
	},

	bind: function() {
		CS.mainPanel = this.mainPanel;

		Ext.each(this.eventItems, function(item) {
			var arr = CS.find(item.query);

			Ext.each(arr, function(one) {
				CS.bind(one, item.event, item.fn);
			});
		});
	}

});
Ext.define('CS.data.proxy.Custom', {
	extend: 'Ext.data.proxy.Server',
	requires: ['Ext.util.MixedCollection', 'Ext.Ajax'],

	actionMethods: {
		create: 'POST',
		read: 'GET',
		update: 'POST',
		destroy: 'POST'
	},

	binary: false,

	doRequest: function(operation, callback, scope) {
		if (operation.action == 'destroy') {
			return null;
		} else {
			var params = operation.params || {};

			params.startIndex = operation.start;
			params.pageSize = operation.limit;

			var request = {
				url: this.url,
				jsonData: Ext.encode(params)
			};

			CS.apply(request, {
				binary: this.binary,
				headers: this.headers,
				timeout: this.timeout,
				scope: this,
				callback: this.createRequestCallback(request, operation, callback, scope),
				method: this.getMethod(request),
				disableCaching: false,
				async: operation.isAsync || true
			});

			Ext.Ajax.request(request);

			return request;
		}
	},

	getMethod: function(request) {
		return this.actionMethods[request.action];
	},

	createRequestCallback: function(request, operation, callback, scope) {
		var me = this;

		return function(options, success, response) {
			me.processResponse(success, operation, request, response, callback, scope);
		};
	}

});
Ext.define('CS.data.reader.Tree', {
	extend: 'Ext.data.reader.Json',

	childrenPro: 'children',

	getResponseData: function(response) {
		var me = this, data, error;

		try {
			data = Ext.decode(response.responseText);

			if (CS.isNotEmpty(data.data)) {
				me.loopInit(data.data);
			}

			return this.readRecords(data);
		} catch (ex) {
			error = new Ext.data.ResultSet({
				total: 0,
				count: 0,
				records: [],
				success: false,
				message: ex.message
			});

			this.fireEvent('exception', this, response, error);

			Ext.Logger.warn('Unable to parse the JSON returned by the server');

			return error;
		}
	},

	loopInit: function(data) {
		var me = this;

		Ext.each(data, function(one) {
			one.leaf = CS.getBoolean(one.leaf);
			one.expanded = CS.getBoolean(one.expanded);

			if (me.needCheck) {
				one.checked = CS.getBoolean(one.checked);
			} else {
				delete one.checked;
			}

			var children = one[me.childrenPro];
			if (CS.isNotEmpty(children)) {
				me.loopInit(children);
			}
		});
	}

});
Ext.define('CS.data.CustomStore', {
	extend: 'Ext.data.Store',
	requires: ['CS.data.proxy.Custom'],

	constructor: function(config) {
		config = CS.apply({}, config);

		if (CS.isNull(config.data)) {
			config.proxy = {
				type: 'custom',
				url: config.url,
				reader: {
					type: 'json',
					root: 'data',
					totalProperty: 'count'
				}
			};

			delete config.url;
		} else {
			if (Ext.isString(config.data)) {
				var arr = config.data.split(',');
				config.data = [];
				for (var i = 0; i < arr.length; i++) {
					config.data.push(arr[i].split(':'));
				}
			}

			if (CS.isNotEmpty(config.data) && Ext.isArray(config.data[0])) {
				config.proxy = {
					type: 'memory',
					reader: 'array'
				}
			}
		}

		this.callParent([config]);
	}

});
Ext.define('CS.data.TreeStore', {
	extend: 'Ext.data.TreeStore',
	requires: ['CS.data.proxy.Custom', 'CS.data.reader.Tree'],

	rootPro: 'data',

	childrenPro: 'children',

	isAsync: false,

	constructor: function(config) {
		var me = this;

		config = CS.apply({}, config);

		config.defaultRootProperty = config.rootPro || me.rootPro;
		config.childrenPro = config.childrenPro || me.childrenPro;

		config.proxy = {
			type: 'custom',
			url: config.url,
			reader: {
				type: 'tree',
				childrenPro: config.childrenPro,
				needCheck: config.needCheck
			}
		};

		delete config.url;

		me.callParent([config]);
	},

	onNodeAdded: function(parent, node) {
		var me = this, proxy = me.getProxy(), reader = proxy.getReader(), data = node.raw
				|| node[node.persistenceProperty], dataRoot;

		Ext.Array.remove(me.removed, node);
		node.join(me);

		if (!node.isLeaf() && !me.lazyFill) {
			if (node.isRoot() || me.isAsync) {
				dataRoot = reader.getRoot(data);
			} else {
				dataRoot = data[me.childrenPro] || [];
			}
			if (dataRoot) {
				me.fillNode(node, reader.extractData(dataRoot));
				delete data[reader.root];
			}
		}

		if (me.autoSync && !me.autoSyncSuspended && (node.phantom || node.dirty)) {
			me.sync();
		}
	},

	setRootNode: function(root, preventLoad) {
		var me = this, model = me.model, idProperty = model.prototype.idProperty

		root = root || {};
		if (!root.isModel) {
			root = Ext.apply({}, root);
			Ext.applyIf(root, {
				id: me.defaultRootId,
				text: me.defaultRootText,
				allowDrag: false
			});
			if (root[idProperty] === undefined) {
				root[idProperty] = me.defaultRootId;
			}
			Ext.data.NodeInterface.decorate(model);
			root = Ext.ModelManager.create(root, model);
		} else if (root.isModel && !root.isNode) {
			Ext.data.NodeInterface.decorate(model);
		}

		me.getProxy().getReader().buildExtractors(true);

		me.tree.setRootNode(root);

		if (preventLoad !== true && !root.isLoaded() && me.autoLoad === true) {
			root.data.expanded = false;
			root.expand();
		}

		return root;
	},

	reload: function(options) {
		this.lastOptions = this.lastOptions || {};

		return this.load(Ext.apply(this.lastOptions, options));
	}

});
Ext.define('CS.plugin.BasePlugin', {
	extend: 'Ext.AbstractPlugin',

	init: function(panel) {
		var me = this;

		if (me.ignoreExist) {
			CS.apply(panel, null, me.extFn);
		} else {
			CS.apply(panel, me.extFn);
		}
	}

});
Ext.define('CS.plugin.FieldDataDeal', {
	extend: 'CS.plugin.BasePlugin',

	ignoreExist: true,

	extFn: {
		getData: function() {
			return this.getValue();
		},
		setData: function(data) {
			this.setValue(data);
		},
		clear: function() {
			var me = this;

			if (me.clearValue) {
				me.clearValue();
			} else {
				me.setData('');
			}
		}
	}

});
Ext.define('CS.plugin.FieldDomDeal', {
	extend: 'CS.plugin.BasePlugin',

	extFn: {
		parent: function() {
			return this.up();
		}
	}

});
Ext.define('CS.plugin.GridRender', {
	extend: 'CS.plugin.BasePlugin',

	extFn: {
		renderField: function(value, field) {
			if (field.getTextByValue) {
				return field.getTextByValue(value);
			} else {
				return value;
			}
		}
	}

});
Ext.define('CS.plugin.PanelDataDeal', {
	extend: 'CS.plugin.BasePlugin',

	ignoreExist: true,

	extFn: {
		getData: function(notNeedCls) {
			var data = {};

			if (this.isForm) {
				this.items.each(function(item) {
					var cls = item.clsName, name = item.clsParam;

					if (CS.isNull(cls) || notNeedCls == true) {
						data[name] = item.getData();
					} else {
						if (CS.isNull(data[cls])) {
							data[cls] = {};
						}

						data[cls][name] = item.getData();
					}
				});
			} else {
				Ext.each(this.children(), function(item) {
					if (CS.isNotNull(item.getData)) {
						data = Ext.merge(data, item.getData(notNeedCls));
					}
				});
			}

			return data;
		},
		setData: function(data, notNeedCls) {
			if (this.isForm) {
				this.items.each(function(item) {
					var cls = item.clsName, name = item.clsParam;

					if ((CS.isNull(cls) || notNeedCls == true) && CS.isNotNull(data[name])) {
						item.setData(data[name]);
					} else if (CS.isNotNull(data[cls]) && CS.isNotNull(data[cls][name])) {
						item.setData(data[cls][name]);
					}
				});
			} else {
				Ext.each(this.children(), function(item) {
					if (CS.isNotNull(item.setData)) {
						item.setData(data, notNeedCls);
					}
				});
			}
		},
		clear: function() {
			Ext.each(this.children(), function(item) {
				if (CS.isNotNull(item.clear)) {
					item.clear();
				}
			});
		},
		setReadOnly: function(readOnly) {
			if (CS.isNull(readOnly)) {
				readOnly = true;
			}

			Ext.each(this.children(), function(item) {
				if (CS.isNotNull(item.setReadOnly)) {
					item.setReadOnly(readOnly);
				}
			});
		}
	}

});
Ext.define('CS.plugin.PanelDomDeal', {
	extend: 'CS.plugin.BasePlugin',

	ignoreExist: true,

	extFn: {
		parent: function() {
			return this.up();
		},
		get: function(id) {
			return this.getComponent(id);
		},
		children: function() {
			return this.query('>');
		}
	}

});
Ext.define('CS.tool.PagingToolbar', {
	extend: 'Ext.PagingToolbar',
	requires: ['CS.data.CustomStore'],

	prependButtons: true,

	displayInfo: true,

	displayMsg: '{0} - {1} 共 {2}',

	pageSizeData: undefined,

	defaultPageSizeData: [[10, 10], [20, 20], [50, 50], [100, 100]],

	store: undefined,

	pageSize: undefined,

	constructor: function(config) {
		var me = this;

		config = CS.apply({}, config);

		config.pageSizeData = [];
		CS.apply(config.pageSizeData, me.defaultPageSizeData);

		var tempNum = 0;
		for (; tempNum < config.pageSizeData.length; tempNum++) {
			var arr = config.pageSizeData[tempNum];

			if (arr[0] == config.pageSize) {
				tempNum = -1;
				break;
			} else if (arr[0] > config.pageSize) {
				break;
			}
		}
		if (tempNum > -1) {
			config.pageSizeData.splice(tempNum, 0, [config.pageSize, config.pageSize]);
		}

		config.items = [{
			xtype: 'field.combo',
			width: 80,
			fields: 'code,description',
			localData: config.pageSizeData,
			value: config.pageSize,
			needTextTpl: false,
			listeners: {
				change: function(conbo, value) {
					me.reload(value);
				}
			}
		}];

		me.callParent([config]);
	},

	reload: function(pageSize) {
		this.store.pageSize = pageSize;
		this.store.loadPage(1, this.store.lastParams);
	},

	moveFirst: function() {
		if (this.fireEvent('beforechange', this, 1) !== false) {
			this.store.loadPage(1, this.store.lastParams);
		}
	},

	movePrevious: function() {
		var prev = this.store.currentPage - 1;

		if (prev > 0) {
			if (this.fireEvent('beforechange', this, prev) !== false) {
				this.store.previousPage(this.store.lastParams);
			}
		}
	},

	moveNext: function() {
		var next = this.store.currentPage + 1;

		if (next <= this.getPageData().pageCount) {
			if (this.fireEvent('beforechange', this, next) !== false) {
				this.store.nextPage(this.store.lastParams);
			}
		}
	},

	moveLast: function() {
		var last = this.getPageData().pageCount;

		if (this.fireEvent('beforechange', this, last) !== false) {
			this.store.loadPage(last, this.store.lastParams);
		}
	},

	doRefresh: function() {
		var current = this.store.currentPage;

		if (this.fireEvent('beforechange', this, current) !== false) {
			this.store.loadPage(current, this.store.lastParams);
		}
	}

});
Ext.define('CS.field.BaseField', {
	extend: 'CS.config.BaseConfig',
	requires: ['CS.plugin.FieldDataDeal', 'CS.plugin.FieldDomDeal'],

	transform: {
		clsName: 'className',
		clsParam: 'name',
		fieldLabel: 'label',
		multiSelect: 'multi'
	},

	defaultConfig: {
		labelAlign: 'right',
		multiSelect: false,
		needTextTpl: false,
		selectAll: false,
		width: 300
	},

	defaultPlugins: ['fielddatadeal', 'fielddomdeal'],

	initConfig: function(config) {
		config.xtype = 'field.' + config.fieldType;

		config.itemId = '';
		if (CS.isNotEmpty(config.clsName)) {
			config.itemId += config.clsName + '_';
		}
		config.itemId += config.clsParam;
	}

});
Ext.define('CS.field.Combo', {
	extend: 'Ext.form.field.ComboBox',
	requires: ['CS.data.CustomStore'],

	minChars: 0,

	triggerAction: 'all',

	allQuery: '',

	queryDelay: 300,

	filterValid: false,

	constructor: function(config) {
		var me = this;

		config = CS.apply({}, config);

		config.isLoad = CS.getBoolean(config.isLoad, true);

		config.listeners = config.listeners || {};

		var fields = config.fields.split(',');
		config.valueField = fields[0];
		config.displayField = fields[1];

		if (CS.isNotEmpty(config.url)) {
			config.queryMode = 'remote';
			config.queryParam = config.valueField;

			config.store = Ext.create('CS.data.CustomStore', {
				url: config.url,
				fields: fields,
				autoLoad: config.isLoad,
				listeners: {
					beforeload: function(store, option) {
						option.params = option.params || {};
						CS.apply(option.params, me.extendParam);
					}
				}
			});

			if (config.selectAll) {
				var selectAll = {};
				selectAll[config.valueField] = '';
				selectAll[config.displayField] = '所有';

				config.store.addListener('load', function(store, records) {
					store.insert(0, selectAll);
				});
			}
		} else {
			config.queryMode = 'local';

			if (config.selectAll) {
				config.localData = ':所有,' + config.localData;
			}

			config.store = Ext.create('CS.data.CustomStore', {
				data: config.localData,
				fields: fields
			});
		}

		if (CS.isNotNull(config.value)) {
			config.value += '';
		}

		if (config.needTextTpl != false) {
			if (CS.isNull(config.textTpl)) {
				config.textTpl = '{' + config.displayField + '} ({' + config.valueField + '})';
			}
			config.listConfig = {
				getInnerTpl: function() {
					return config.textTpl;
				}
			};
		}

		config.listeners.blur = function() {
			if (CS.isEmpty(me.getDisplayValue()) && CS.isNotEmpty(me.getText())) {
				var store = me.picker.getStore();

				if (store.getCount() > 0) {
					me.setData(store.getAt(0).get(me.valueField));
				} else {
					me.clear();
				}
			}
		};

		me.callParent([config]);
	},

	doQuery: function(queryString, forceAll, rawQuery) {
		var me = this,

		queryPlan = me.beforeQuery({
			query: queryString || '',
			rawQuery: rawQuery,
			forceAll: forceAll,
			combo: me,
			cancel: false
		});

		if (queryPlan === false || queryPlan.cancel) {
			return false;
		}

		if (me.queryCaching && queryPlan.query === me.lastQuery) {
			me.expand();
		} else {
			me.lastQuery = queryPlan.query;
			me.doLocalQuery(queryPlan);
		}

		return true;
	},

	getText: function() {
		return this.getRawValue();
	},

	getTextByValue: function(value) {
		var me = this;

		var record = me.findRecord(me.valueField, value);
		return record ? record.get(me.displayField) : me.valueNotFoundText;
	},

	addParam: function(param) {
		if (Ext.isObject(param)) {
			CS.apply(this.extendParam, param);
		}
	},

	cleanParam: function() {
		for (var i = 0; i < arguments.length; i++) {
			delete this.extendParam[arguments[i]];
		}
	},

	cleanAllParam: function() {
		this.extendParam = {};
	},

	reload: function(params, callbackFn) {
		var me = this, newParams = params || {};

		me.reset();

		newParams[me.valueField] = '';

		me.store.load({
			params: params,
			callback: callbackFn
		});
	}

});
Ext.define('CS.field.Date', {
	extend: 'Ext.form.field.Date',

	format: 'Y-m-d',

	getData: function() {
		return Ext.util.Format.date(this.getValue(), this.format);
	}

});
Ext.define('CS.field.Number', {
	extend: 'Ext.form.field.Number'

});
Ext.define('CS.field.Password', {
	extend: 'Ext.form.field.Text',

	inputType: 'password'

});
Ext.define('CS.field.Text', {
	extend: 'Ext.form.field.Text'

});
Ext.define('CS.page.BasePage', {
	extend: 'CS.config.BaseConfig',

	transform: {
		pageTitle: 'title',
		itemId: 'pageId'
	},

	defaultConfig: {
		border: false
	},

	initConfig: function(config) {
		config.panel.pageTitle = config.pageTitle;

		config.panel = Ext.create('CS.panel.BasePanel', config.panel).getConfig();
	}

});
Ext.define('CS.page.Main', {
	requires: ['CS.page.BasePage'],

	mainPanel: undefined,

	constructor: function(config) {
		var me = this;

		config = Ext.create('CS.page.BasePage', config).getConfig();

		me.mainPanel = CS.create(config.panel);

		window.onresize = function() {
			me.mainPanel.doLayout();
		};
	},

	bind: function(eventItems) {
		var me = this, config = {};

		var config = CS.apply({}, {
			eventItems: eventItems,
			mainPanel: me.mainPanel
		});

		Ext.create('CS.controller.PageController', config).bind();
	},

	render: function() {
		this.mainPanel.render(Ext.getBody());
	},

	getData: function() {
		return this.mainPanel.getData();
	},

	setData: function(data) {
		this.mainPanel.setData(data);
	}

});
Ext.define('CS.panel.BasePanel', {
	extend: 'CS.config.BaseConfig',
	requires: ['CS.plugin.PanelDataDeal', 'CS.plugin.PanelDomDeal'],

	transform: {
		autoShow: 'show',
		bottomAlign: 'bAlign',
		clsName: 'fieldClassName',
		closeAction: 'closeType',
		itemId: 'panelId'
	},

	defaultConfig: {
		autoHeight: true,
		autoRender: true,
		border: false,
		bottomAlign: 'center',
		clsName: '',
		isAsync: false,
		paging: true,
		pageSize: 10
	},

	defaultPlugins: ['paneldatadeal', 'paneldomdeal'],

	initConfig: function(config) {
		var me = this;

		if (CS.isNull(config.xtype)) {
			config.xtype = 'panel.' + config.panelType;
		}

		me.initItems(config);
		me.initButtons(config);
	},

	initItems: function(config) {
		config.items = config.items || [];

		if (CS.isNotEmpty(config.subFieldList)) {
			Ext.each(config.subFieldList, function(fieldConfig) {
				config.items.push(Ext.create('CS.field.BaseField', fieldConfig).getConfig());
			});
		} else if (CS.isNotEmpty(config.subPanelList)) {
			Ext.each(config.subPanelList, function(panelConfig) {
				config.items.push(Ext.create('CS.panel.BasePanel', panelConfig).getConfig());
			});
		}

		delete config.subFieldList;
		delete config.subPanelList;
	},

	initButtons: function(config) {
		if (CS.isNotEmpty(config.buttonList)) {
			var tbar = {
				xtype: 'toolbar',
				dock: 'top',
				items: []
			};

			var bbar = {
				xtype: 'toolbar',
				dock: 'bottom',
				ui: 'footer',
				layout: {
					pack: config.bottomAlign
				},
				items: []
			};

			Ext.each(config.buttonList, function(button, index) {
				var item = {
					itemId: button.buttonId,
					text: button.text
				};

				if (CS.isNotEmpty(button.icon)) {
					item.iconCls = 'cs-icon-' + button.icon;
				}

				switch (button.buttonSite) {
				case 't':
					if (CS.isNotEmpty(tbar.items)) {
						tbar.items.push('-');
					}
					tbar.items.push(item);
					break;
				case 'b':
					if (index > 0) {
						bbar.items.push({
							xtype: 'tbspacer',
							width: 20
						});
					} else if (config.bottomAlign == 'right') {
						bbar.items.push('->');
					}

					bbar.items.push(item);
					break;
				}
			});

			config.dockedItems = [];
			if (CS.isNotEmpty(tbar.items)) {
				config.dockedItems.push(tbar);
			}

			if (CS.isNotEmpty(bbar.items)) {
				config.dockedItems.push(bbar);
			}
		}
	}

});
Ext.define('CS.panel.Form', {
	extend: 'Ext.panel.Panel',

	isForm: true,

	maxCol: 2,

	layout: {
		type: 'table',
		tableAttrs: {
			style: {
				width: '100%'
			}
		}
	},

	defaults: {
		margin: '6 3 6 3'
	},

	constructor: function(config) {
		var me = this;

		config = CS.apply({}, config);

		config.maxCol = config.maxCol || me.maxCol;

		me.layout.columns = config.maxCol;

		if (config.maxCol == 1) {
			me.layout.tdAttrs = {
				align: 'center'
			};
		}

		me.callParent([config]);
	}

});
Ext.define('CS.panel.Grid', {
	extend: 'Ext.grid.GridPanel',
	requires: ['CS.data.CustomStore', 'CS.tool.PagingToolbar', 'CS.plugin.GridRender'],

	columnLines: true,

	constructor: function(config) {
		var me = this;

		config = CS.apply({}, config);

		config.plugins.push('gridrender');

		config.columns = [];
		config.columns.push({
			xtype: 'rownumberer',
			width: 70,
			text: '序号',
			align: 'center'
		});

		if (CS.isNotEmpty(config.fields)) {
			var obj = CS.transKeyValue(config.fields);

			config.items = [];

			for (param in obj) {
				config.items.push({
					xtype: 'field.text',
					fieldLabel: obj[param],
					clsParam: param
				});
			}

			delete config.fields;
		}

		var fields = [];
		Ext.each(config.items, function(item) {
			var col = {};

			col.text = item.fieldLabel;
			col.dataIndex = item.clsParam;

			item.hideLabel = true;
			col.field = CS.create(item);
			col.renderer = me.render;

			if (CS.isNotNull(item.colAlign)) {
				col.align = item.colAlign;
			} else {
				col.align = 'center';
			}

			if (CS.isNotNull(item.colWidth)) {
				col.width = item.colWidth;
			} else {
				col.flex = 1;
			}

			if (CS.isNotNull(item.hidden)) {
				col.hidden = item.hidden;
			}

			config.columns.push(col);
			fields.push(item.clsParam);
		});
		delete config.items;

		config.isLoad = CS.getBoolean(config.isLoad);

		var lastParams = {
			params: config.extendParam
		};
		if (config.paging) {
			config.store = Ext.create('CS.data.CustomStore', {
				url: config.url,
				fields: fields,
				pageSize: config.pageSize,
				lastParams: lastParams,
				autoLoad: config.isLoad ? lastParams : false
			});

			config.bbar = Ext.create('CS.tool.PagingToolbar', {
				store: config.store,
				pageSize: config.pageSize
			});
		} else {
			config.store = Ext.create('CS.data.CustomStore', {
				url: config.url,
				fields: fields,
				lastParams: lastParams,
				autoLoad: config.isLoad ? lastParams : false
			});
		}

		me.callParent([config]);
	},

	render: function(value, metaData) {
		var field = metaData.column.field;

		return this.renderField.apply(this, [value, field]);
	},

	renderField: function(value) {
		return value;
	},

	reload: function(params, callbackFn) {
		var me = this;

		me.store.lastParams = {
			params: CS.apply(params || {}, me.extendParam),
			callback: callbackFn
		};

		me.store.loadPage(1, me.store.lastParams);
	},

	getCurrentParam: function() {
		return this.store.lastParams.params;
	},

	getSelected: function(notNeedCls) {
		var me = this, selected = me.getSelectionModel().getSelection(), clsName = me.clsName, data = null;

		if (selected.length > 0) {
			data = selected[0].getData();
		}

		return CS.getPackageData(data, clsName, notNeedCls);
	},

	getSelection: function(notNeedCls) {
		var me = this, selected = me.getSelectionModel().getSelection(), clsName = me.clsName, data = [];

		Ext.each(selected, function(record) {
			data.push(record.getData());
		});

		return CS.getPackageData(data, clsName, notNeedCls);
	},

	getData: function(notNeedCls) {
		var me = this, data = [], clsName = me.clsName, records = me.store.getRange();

		Ext.each(records, function(record) {
			data.push(record.getData());
		});

		return CS.getPackageData(data, clsName, notNeedCls);
	},

	setData: function(data, notNeedCls) {
		var me = this;

		me.store.removeAll();

		if (notNeedCls != true) {
			data = data[me.clsName];
		}

		Ext.each(data, function(one) {
			me.store.add(one);
		});
	}

});
Ext.define('CS.panel.HBox', {
	extend: 'Ext.panel.Panel',

	layout: 'hbox',

	constructor: function(config) {
		var me = this;

		config = CS.apply({}, config);

		Ext.each(config.items, function(item) {
			if (CS.isNotNull(item.colWidth)) {
				item.width = item.colWidth;
			} else {
				item.flex = 1;
				delete item.width;
			}
		});

		me.callParent([config]);
	}

});
Ext.define('CS.panel.List', {
	extend: 'Ext.panel.Panel',

	layout: 'anchor',

	constructor: function(config) {
		var me = this;

		config = CS.apply({}, config);

		me.callParent([config]);
	}

});
Ext.define('CS.panel.Pie', {
	extend: 'Ext.chart.Chart',

	textField: undefined,

	countField: undefined,

	animate: true,

	legend: {
		position: 'bottom'
	},

	insetPadding: 30,

	shadow: true,

	constructor: function(config) {
		var me = this;

		config = CS.apply({}, config);

		if (CS.isNull(config.isLoad)) {
			config.isLoad = true;
		}

		var fields = config.fields.split(',');
		config.textField = fields[0];
		config.countField = fields[1];

		config.store = Ext.create('CS.data.CustomStore', {
			url: config.url,
			fields: fields,
			autoLoad: config.isLoad
		});

		config.series = [{
			type: 'pie',
			field: config.countField,
			showInLegend: true,
			donut: false,
			label: {
				field: config.textField,
				display: 'middle',
				contrast: true,
				font: '18px Arial'
			},
			highlight: {
				segment: {
					margin: 20
				}
			},
			tips: {
				trackMouse: true,
				width: 140,
				height: 28,
				renderer: function(storeItem) {
					var total = 0;
					me.store.each(function(rec) {
						total += rec.get(config.countField);
					});
					this.setTitle(Math.round(storeItem.get(config.countField) / total * 100) + '%');
				}
			}
		}];

		me.callParent([config]);
	}

});
Ext.define('CS.panel.Tab', {
	extend: 'Ext.tab.Panel',

	constructor: function(config) {
		var me = this;

		config = CS.apply({}, config);

		me.callParent([config]);
	},

	showTab: function(card) {
		var item = this.getComponent(card);

		if (item && item.tab) {
			item.tab.show();
			this.setActiveTab(item);
		}
	},

	hideTab: function(card) {
		var item = this.getComponent(card), toActivate;

		if (item && item.tab) {
			item.tab.hide();

			if ((toActivate = this.tabBar.items.indexOf(this.tabBar.findNextActivatable(item.tab))) !== -1) {
				this.setActiveTab(toActivate);
			}
		}
	},

	loadTab: function(id, title, url, notActive) {
		var me = this, options = {
			panelType: 'list',
			closable: true
		};

		if (Ext.isString(id)) {
			CS.apply(options, {
				panelId: id,
				title: title,
				html: '<iframe frameborder="0" width=100% height=100% src="' + CS.getRootUrl(url) + '" />'
			});
		} else {
			CS.apply(options, id);
		}

		var tab = CS.create(Ext.create('CS.panel.BasePanel', options).getConfig());
		me.add(tab);

		if (notActive != true) {
			me.showTab(tab);
		}

		return tab;
	}

});
Ext.define('CS.panel.Tree', {
	extend: 'Ext.tree.Panel',
	requires: ['CS.data.TreeStore'],

	rootVisible: false,

	useArrows: true,

	constructor: function(config) {
		var me = this;

		config = CS.apply({}, config);

		config.listeners = config.listeners || {};

		if (config.needCheck) {
			config.listeners.checkchange = function(node, checked) {
				if (window.event.ctrlKey) {
					node.cascadeBy(function(child) {
						child.set('checked', checked);
					});
				}

				if (!checked) {
					node.bubble(function(parentNode) {
						parentNode.set('checked', false);
					});
				}
			};
		}

		config.isLoad = CS.getBoolean(config.isLoad, true);

		var storeConfig = {
			url: config.url,
			isAsync: config.isAsync,
			autoLoad: config.isLoad,
			needCheck: config.needCheck
		};

		if (config.fields) {
			storeConfig.fields = config.fields.split(',');
		}

		config.store = Ext.create('CS.data.TreeStore', storeConfig);

		me.callParent([config]);
	},

	clear: function() {
		var root = this.getRootNode();

		if (root.childNodes) {
			root.removeAll();
		}
	},

	reload: function(params, callbackFn) {
		var me = this;

		me.store.reload({
			params: CS.apply(params || {}, me.extendParam),
			callback: callbackFn
		});
	},

	getSelection: function(notNeedCls) {
		var me = this, clsName = me.clsName, data = [];

		me.getRootNode().cascadeBy(function(child) {
			if (child.get('checked')) {
				data.push(child.data);
			}
		});

		return CS.getPackageData(data, clsName, notNeedCls);
	}

});
Ext.define('CS.panel.VBox', {
	extend: 'Ext.panel.Panel',

	layout: {
		type: 'vbox',
		align: 'stretch'
	},

	constructor: function(config) {
		var me = this;

		config = CS.apply({}, config);

		me.callParent([config]);
	}

});
Ext.define('CS.panel.View', {
	extend: 'Ext.container.Viewport',

	layout: 'border',

	padding: '5 5 5 5',

	constructor: function(config) {
		var me = this;

		config = CS.apply({}, config);

		me.callParent([config]);
	},

	initComponent: function() {
		var me = this;

		me.callParent();

		me.renderTo = null;
	}

});
Ext.define('CS.panel.Win', {
	extend: 'Ext.window.Window',

	closable: true,

	closeAction: 'hide',

	resizable: false,

	layout: 'fit',

	autoScroll: true,

	constructor: function(config) {
		var me = this;

		config = CS.apply({}, config);

		if (CS.isNotEmpty(config.x) || CS.isNotEmpty(config.y)) {
			config.listeners = config.listeners || {};
			config.listeners.show = function() {
				if (CS.isNotEmpty(config.x)) {
					me.setX(config.x);
				}
				if (CS.isNotEmpty(config.y)) {
					me.setY(config.y);
				}
			};
		}

		me.callParent([config]);
	},

	show: function() {
		this.center();
		this.callParent(arguments);
	}

});
Ext.define('CS.panel.EditGrid', {
	extend: 'CS.panel.Grid',
	requires: ['Ext.grid.plugin.CellEditing'],

	editing: Ext.create('Ext.grid.plugin.CellEditing', {
		clicksToMoveEditor: 1,
		autoCancel: false
	}),

	constructor: function(config) {
		var me = this;

		config = CS.apply({}, config);

		config.plugins.push(me.editing);

		config.paging = false;

		me.callParent([config]);
	}

});
Ext.define('CS.panel.Multi', {
	extend: 'CS.panel.HBox',
	requires: ['CS.panel.VBox'],

	headCls: Ext.baseCSSPrefix + 'multi-head',

	infoPanel: undefined,

	headPanel: undefined,

	contentPanel: undefined,

	operatePanel: undefined,

	deletePanel: undefined,

	constructor: function(config) {
		var me = this;

		config = CS.apply({}, config);

		config.tools = [{
			type: 'plus',
			tooltip: '新增',
			handler: function() {
				me.addRow();
			}
		}, {
			type: 'minus',
			tooltip: '清空',
			handler: function() {
				CS.confirm('将会清空所有数据，请确认', function() {
					me.clear();
				});
			}
		}];

		me.createHead(config);
		me.createContent(config);
		me.createInfo(config);
		me.createDelete(config);
		me.createOperate(config);

		config.items = [config.infoPanel, config.operatePanel];

		me.callParent([config]);
	},

	initComponent: function() {
		var me = this;

		me.addEvents('beforeaddrow', 'addrow', 'beforeremoverow', 'removerow');

		me.callParent(arguments);
	},

	createHead: function(config) {
		var me = this;

		var headConfig = {
			xtype: 'panel.hbox',
			border: false,
			defaults: {
				xtype: 'panel',
				bodyCls: me.headCls,
				margin: '3 0 3 3'
			},
			items: []
		};

		Ext.each(config.items, function(item) {
			headConfig.items.push({
				html: item.fieldLabel,
				colWidth: item.colWidth
			});
		});

		config.headPanel = CS.create(headConfig);

		return config.headPanel;
	},

	createContent: function(config) {
		var me = this, itemConfig = config.items;

		Ext.each(itemConfig, function(item) {
			item.itemId = item.clsParam;
			delete item.fieldLabel;
		});

		config.contentPanel = CS.create({
			xtype: 'panel.vbox',
			border: false,
			defaults: {
				xtype: 'panel.hbox',
				border: false,
				defaults: {
					margin: '0 0 3 3'
				}
			},
			defaultConfig: {
				xtype: 'panel.hbox',
				plugins: ['paneldatadeal', 'paneldomdeal'],
				border: false,
				defaults: {
					margin: '0 0 3 3'
				},
				items: itemConfig
			},
			addRow: function(cmp) {
				if (!cmp) {
					cmp = me.createRow(me.contentPanel.defaultConfig);
				}

				return me.contentPanel.add(cmp);
			}
		});

		return config.contentPanel;
	},

	createRow: function(config) {
		config = CS.apply({}, config);

		return CS.create(config);
	},

	createInfo: function(config) {
		config.infoPanel = CS.create({
			xtype: 'panel.vbox',
			border: false,
			items: [config.headPanel, config.contentPanel]
		});

		return config.infoPanel;
	},

	createDelete: function(config) {
		var me = this;

		config.deletePanel = CS.create({
			xtype: 'panel.vbox',
			border: false,
			addDelete: function(row) {
				var button = CS.create({
					xtype: 'button',
					text: '删除',
					margin: '0 3 3 3',
					handler: function() {
						me.removeRow(me.deletePanel.items.indexOf(button));
					}
				});

				me.deletePanel.add(button);

				return button;
			}
		});

		return config.deletePanel;
	},

	createOperate: function(config) {
		var me = this;

		config.operatePanel = CS.create({
			xtype: 'panel.vbox',
			colWidth: 100,
			border: false,
			items: [{
				xtype: 'panel',
				border: true,
				bodyCls: me.headCls,
				margin: '3',
				html: '操作'
			}, config.deletePanel]
		});

		return config.operatePanel;
	},

	addRow: function(cmp) {
		var me = this;

		me.fireEvent('beforeaddrow', cmp);

		var row = me.contentPanel.addRow(cmp);
		var button = me.deletePanel.addDelete(row);

		me.fireEvent('addrow', row, button);

		return row;
	},

	count: function() {
		return this.contentPanel.items.getCount();
	},

	getRow: function(num) {
		if (CS.isNull(num)) {
			num = me.count() - 1;
		}

		if (num >= 0) {
			return this.contentPanel.getComponent(num).items.getRange();
		} else {
			return null;
		}
	},

	getRows: function(start, end) {
		var me = this, itemArr = [];

		if (CS.isNull(start)) {
			start = 0;
		}

		if (CS.isNull(end)) {
			end = me.count() - 1;
		}

		for (; start <= end; start++) {
			var row = me.contentPanel.getComponent(start);
			itemArr.push(row.items.getRange());
		}

		return itemArr;
	},

	removeRow: function(num) {
		var me = this;

		if (CS.isNull(num)) {
			num = me.count() - 1;
		}

		if (num >= 0) {
			var row = me.contentPanel.getComponent(num);
			var button = me.deletePanel.getComponent(num);

			me.fireEvent('beforeremoverow', num, row, button);

			me.contentPanel.remove(row);
			me.deletePanel.remove(button);

			me.fireEvent('removerow', num);
		}
	},

	reload: function(params, callbackFn, lock) {
		var me = this;

		CS.ajax({
			url: me.url,
			data: params,
			lock: lock,
			succ: function(data) {
				me.setData(data.data, true);
			}
		});
	},

	getData: function(notNeedCls) {
		var me = this, data = [], clsName = me.clsName, rows = me.getRows();

		Ext.each(rows, function(row) {
			var rowData = {};

			Ext.each(row, function(item) {
				rowData[item.clsParam] = item.getData();
			});

			data.push(rowData);
		});

		return CS.getPackageData(data, clsName, notNeedCls);
	},

	setData: function(data, notNeedCls) {
		var me = this;

		if (notNeedCls != true) {
			data = data[me.clsName];
		}

		if (Ext.isObject(data)) {
			data = [data];
		}

		for (var i = 0; i < data.length; i++) {
			var rowData = data[i];

			me.addRow().items.each(function(item) {
				item.setData(rowData[item.clsParam]);
			});
		}
	},

	clear: function() {
		var size = this.count();

		for (var i = 0; i < size; i++) {
			this.removeRow();
		}
	},

	children: function() {
		var children = [], rows = this.getRows();

		Ext.each(rows, function(row) {
			children = children.concat(row);
		});

		return children;
	},

	getSibling: function(cmp, name) {
		return cmp.up().get(name);
	}

});